﻿Imports System
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Drawing
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler
Imports System.Workflow.ComponentModel.Design

Namespace System.Workflow.Activities
    <ActivityValidator(GetType(WhileValidator)), ToolboxBitmap(GetType(WhileActivity), "Resources.While.png"), ToolboxItem(GetType(ActivityToolboxItem)), SRDescription("WhileActivityDescription"), Designer(GetType(WhileDesigner), GetType(IDesigner))> _
    Public NotInheritable Class WhileActivity
        Inherits CompositeActivity
        Implements IActivityEventListener([Of] ActivityExecutionStatusChangedEventArgs)
        ' Methods
        Public Sub New()
        End Sub

        Public Sub New(ByVal name As String)
            MyBase.New(name)
        End Sub

        Protected Overrides Function Cancel(ByVal executionContext As ActivityExecutionContext) As ActivityExecutionStatus
            If (executionContext Is Nothing) Then
                Throw New ArgumentNullException("executionContext")
            End If
            If (MyBase.EnabledActivities.Count = 0) Then
                Return ActivityExecutionStatus.Closed
            End If
            Dim activity As Activity = MyBase.EnabledActivities.Item(0)
            Dim context As ActivityExecutionContext = executionContext.ExecutionContextManager.GetExecutionContext(activity)
            If (context Is Nothing) Then
                Return ActivityExecutionStatus.Closed
            End If
            If (context.Activity.ExecutionStatus = ActivityExecutionStatus.Executing) Then
                context.CancelActivity(context.Activity)
            End If
            Return ActivityExecutionStatus.Canceling
        End Function

        Protected Overrides Function Execute(ByVal executionContext As ActivityExecutionContext) As ActivityExecutionStatus
            If (executionContext Is Nothing) Then
                Throw New ArgumentNullException("executionContext")
            End If
            If Me.TryNextIteration(executionContext) Then
                Return ActivityExecutionStatus.Executing
            End If
            Return ActivityExecutionStatus.Closed
        End Function

        Private Sub System.Workflow.ComponentModel.IActivityEventListener<System.Workflow.ComponentModel.ActivityExecutionStatusChangedEventArgs>.OnEvent(ByVal sender As Object, ByVal e As ActivityExecutionStatusChangedEventArgs) Implements IActivityEventListener([Of] ActivityExecutionStatusChangedEventArgs).OnEvent
            If (e Is Nothing) Then
                Throw New ArgumentNullException("e")
            End If
            If (sender Is Nothing) Then
                Throw New ArgumentNullException("sender")
            End If
            Dim context As ActivityExecutionContext = [TryCast](sender,ActivityExecutionContext)
            If (context Is Nothing) Then
                Throw New ArgumentException(SR.Error_SenderMustBeActivityExecutionContext, "sender")
            End If
            e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, Me)
            Dim executionContextManager As ActivityExecutionContextManager = context.ExecutionContextManager
            executionContextManager.CompleteExecutionContext(executionContextManager.GetExecutionContext(e.Activity))
            If Not Me.TryNextIteration(context) Then
                context.CloseActivity
            End If
        End Sub

        Private Function TryNextIteration(ByVal context As ActivityExecutionContext) As Boolean
            If (((MyBase.ExecutionStatus = ActivityExecutionStatus.Canceling) OrElse (MyBase.ExecutionStatus = ActivityExecutionStatus.Faulting)) OrElse Not Me.Condition.Evaluate(Me, context)) Then
                Return False
            End If
            If (MyBase.EnabledActivities.Count > 0) Then
                Dim context2 As ActivityExecutionContext = context.ExecutionContextManager.CreateExecutionContext(MyBase.EnabledActivities.Item(0))
                context2.Activity.RegisterForStatusChange(Activity.ClosedEvent, Me)
                context2.ExecuteActivity(context2.Activity)
            End If
            Return True
        End Function


        ' Properties
        <SRDescription("WhileConditionDescr"), SRCategory("Conditions")> _
        Public Property Condition As ActivityCondition
            Get
                Return [TryCast](MyBase.GetValue(WhileActivity.ConditionProperty),ActivityCondition)
            End Get
            Set(ByVal value As ActivityCondition)
                MyBase.SetValue(WhileActivity.ConditionProperty, value)
            End Set
        End Property

        <Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public ReadOnly Property DynamicActivity As Activity
            Get
                If (MyBase.EnabledActivities.Count > 0) Then
                    Dim dynamicActivities As Activity() = MyBase.GetDynamicActivities(MyBase.EnabledActivities.Item(0))
                    If (dynamicActivities.Length <> 0) Then
                        Return dynamicActivities(0)
                    End If
                End If
                Return Nothing
            End Get
        End Property


        ' Fields
        Public Shared ReadOnly ConditionProperty As DependencyProperty = DependencyProperty.Register("Condition", GetType(ActivityCondition), GetType(WhileActivity), New PropertyMetadata(DependencyPropertyOptions.Metadata, New Attribute() { New ValidationOptionAttribute(ValidationOption.Required) }))
    End Class
End Namespace

